import*as e from"../../core/common/common.js";import*as t from"../../core/sdk/sdk.js";import*as i from"../../core/i18n/i18n.js";import*as o from"../../core/root/root.js";import*as n from"../../ui/legacy/components/color_picker/color_picker.js";import*as s from"../../ui/legacy/legacy.js";import*as r from"../../core/platform/platform.js";import*as a from"../../models/text_utils/text_utils.js";import*as l from"../../ui/components/icon_button/icon_button.js";import*as d from"../../ui/legacy/components/data_grid/data_grid.js";import*as c from"../../ui/legacy/components/utils/utils.js";import*as h from"./components/components.js";import*as u from"../../core/host/host.js";class v extends e.ObjectWrapper.ObjectWrapper{currentUrl;constructor(){super(),this.currentUrl=t.TargetManager.TargetManager.instance().inspectedURL(),t.TargetManager.TargetManager.instance().addEventListener(t.TargetManager.Events.InspectedURLChanged,this.#e,this)}#e(){this.currentUrl!==t.TargetManager.TargetManager.instance().inspectedURL()&&(this.currentUrl=t.TargetManager.TargetManager.instance().inspectedURL(),this.dispatchEventToListeners("Reset"))}}var p=Object.freeze({__proto__:null,OverviewController:v});const m={topAppliedToAStatically:"`Top` applied to a statically positioned element",leftAppliedToAStatically:"`Left` applied to a statically positioned element",rightAppliedToAStatically:"`Right` applied to a statically positioned element",bottomAppliedToAStatically:"`Bottom` applied to a statically positioned element",widthAppliedToAnInlineElement:"`Width` applied to an inline element",heightAppliedToAnInlineElement:"`Height` applied to an inline element",verticalAlignmentAppliedTo:"Vertical alignment applied to element which is neither `inline` nor `table-cell`"},g=i.i18n.registerUIStrings("panels/css_overview/CSSOverviewUnusedDeclarations.ts",m),w=i.i18n.getLocalizedString.bind(void 0,g);class f{static add(e,t,i){const o=e.get(t)||[];o.push(i),e.set(t,o)}static checkForUnusedPositionValues(e,t,i,o,n,s,r,a){if("static"===i[o]){if("auto"!==i[n]){const o=w(m.topAppliedToAStatically);this.add(e,o,{declaration:`top: ${i[n]}`,nodeId:t})}if("auto"!==i[s]){const o=w(m.leftAppliedToAStatically);this.add(e,o,{declaration:`left: ${i[s]}`,nodeId:t})}if("auto"!==i[r]){const o=w(m.rightAppliedToAStatically);this.add(e,o,{declaration:`right: ${i[r]}`,nodeId:t})}if("auto"!==i[a]){const o=w(m.bottomAppliedToAStatically);this.add(e,o,{declaration:`bottom: ${i[a]}`,nodeId:t})}}}static checkForUnusedWidthAndHeightValues(e,t,i,o,n,s){if("inline"===i[o]){if("auto"!==i[n]){const o=w(m.widthAppliedToAnInlineElement);this.add(e,o,{declaration:`width: ${i[n]}`,nodeId:t})}if("auto"!==i[s]){const o=w(m.heightAppliedToAnInlineElement);this.add(e,o,{declaration:`height: ${i[s]}`,nodeId:t})}}}static checkForInvalidVerticalAlignment(e,t,i,o,n){if(i[o]&&!i[o].startsWith("inline")&&!i[o].startsWith("table")&&"baseline"!==i[n]){const o=w(m.verticalAlignmentAppliedTo);this.add(e,o,{declaration:`vertical-align: ${i[n]}`,nodeId:t})}}}var b=Object.freeze({__proto__:null,CSSOverviewUnusedDeclarations:f});class S extends t.SDKModel.SDKModel{#t;#i;#o;#n;constructor(e){super(e),this.#t=e.runtimeAgent(),this.#i=e.cssAgent(),this.#o=e.domsnapshotAgent(),this.#n=e.overlayAgent()}highlightNode(t){const i={contentColor:e.Color.PageHighlight.Content.toProtocolRGBA(),showInfo:!0,contrastAlgorithm:o.Runtime.experiments.isEnabled("APCA")?"apca":"aa"};this.#n.invoke_hideHighlight(),this.#n.invoke_highlightNode({backendNodeId:t,highlightConfig:i})}async getNodeStyleStats(){const t=new Map,i=new Map,s=new Map,r=new Map,a=new Map,l=new Map,d=new Map,c=t=>t instanceof e.Color.Legacy?t.hasAlpha()?t.asString("hexa"):t.asString("hex"):t.asString(),h=(t,i,o)=>{if(-1===t)return;const n=w[t];if(!n)return;const s=e.Color.parse(n);if(!s||0===s.asLegacyColor().rgba()[3])return;const r=c(s);if(!r)return;const a=o.get(r)||new Set;return a.add(i),o.set(r,a),s},u=e=>new Set(["altglyph","circle","ellipse","path","polygon","polyline","rect","svg","text","textpath","tref","tspan"]).has(e.toLowerCase()),v=e=>new Set(["iframe","video","embed","img"]).has(e.toLowerCase()),p=(e,t)=>new Set(["tr","td","thead","tbody"]).has(e.toLowerCase())&&t.startsWith("table");let m=0;const{documents:g,strings:w}=await this.#o.invoke_captureSnapshot({computedStyles:["background-color","color","fill","border-top-width","border-top-color","border-bottom-width","border-bottom-color","border-left-width","border-left-color","border-right-width","border-right-color","font-family","font-size","font-weight","line-height","position","top","right","bottom","left","display","width","height","vertical-align"],includeTextColorOpacities:!0,includeBlendedBackgroundColors:!0});for(const{nodes:b,layout:S}of g){m+=S.nodeIndex.length;for(let m=0;m<S.styles.length;m++){const g=S.styles[m],C=S.nodeIndex[m];if(!b.backendNodeId||!b.nodeName)continue;const y=b.backendNodeId[C],x=b.nodeName[C],[k,I,T,M,$,A,E,L,F,O,R,P,_,V,N,D,z,W,U,B,H,G,j,q]=g;h(k,y,t);const Q=h(I,y,i);if(u(w[x])&&h(T,y,r),"0px"!==w[M]&&h($,y,a),"0px"!==w[A]&&h(E,y,a),"0px"!==w[L]&&h(F,y,a),"0px"!==w[O]&&h(R,y,a),P&&-1!==P){const e=w[P],t=l.get(e)||new Map,i="font-size",o="font-weight",n="line-height",s=t.get(i)||new Map,r=t.get(o)||new Map,a=t.get(n)||new Map;if(-1!==_){const e=w[_],t=s.get(e)||[];t.push(y),s.set(e,t)}if(-1!==V){const e=w[V],t=r.get(e)||[];t.push(y),r.set(e,t)}if(-1!==N){const e=w[N],t=a.get(e)||[];t.push(y),a.set(e,t)}t.set(i,s),t.set(o,r),t.set(n,a),l.set(e,t)}const K=Q&&S.blendedBackgroundColors&&-1!==S.blendedBackgroundColors[m]?e.Color.parse(w[S.blendedBackgroundColors[m]]):null;if(Q&&K){const e=new n.ContrastInfo.ContrastInfo({backgroundColors:[K.asString("hexa")],computedFontSize:-1!==_?w[_]:"",computedFontWeight:-1!==V?w[V]:""}),t=Q.asLegacyColor().blendWithAlpha(S.textColorOpacities?S.textColorOpacities[m]:1);e.setColor(t);const i=`${c(t)}_${c(K.asLegacyColor())}`;if(o.Runtime.experiments.isEnabled("APCA")){const o=e.contrastRatioAPCA(),n=e.contrastRatioAPCAThreshold();if(!(!(!o||!n)&&Math.abs(o)>=n)&&o){const e={nodeId:y,contrastRatio:o,textColor:t,backgroundColor:K,thresholdsViolated:{aa:!1,aaa:!1,apca:!0}};s.has(i)?s.get(i).push(e):s.set(i,[e])}}else{const o=e.contrastRatioThreshold("aa")||0,n=e.contrastRatioThreshold("aaa")||0,r=e.contrastRatio()||0;if(o>r||n>r){const e={nodeId:y,contrastRatio:r,textColor:t,backgroundColor:K,thresholdsViolated:{aa:o>r,aaa:n>r,apca:!1}};s.has(i)?s.get(i).push(e):s.set(i,[e])}}}f.checkForUnusedPositionValues(d,y,w,D,z,B,W,U),u(w[x])||v(w[x])||f.checkForUnusedWidthAndHeightValues(d,y,w,H,G,j),-1===q||p(w[x],w[H])||f.checkForInvalidVerticalAlignment(d,y,w,H,q)}}return{backgroundColors:t,textColors:i,textColorContrastIssues:s,fillColors:r,borderColors:a,fontInfo:l,unusedDeclarations:d,elementCount:m}}getComputedStyleForNode(e){return this.#i.invoke_getComputedStyleForNode({nodeId:e})}async getMediaQueries(){const e=await this.#i.invoke_getMediaQueries(),t=new Map;if(!e)return t;for(const i of e.medias){if("linkedSheet"===i.source)continue;const e=t.get(i.text)||[];e.push(i),t.set(i.text,e)}return t}async getGlobalStylesheetStats(){const{result:e}=await this.#t.invoke_evaluate({expression:"(function() {\n      let styleRules = 0;\n      let inlineStyles = 0;\n      let externalSheets = 0;\n      const stats = {\n        // Simple.\n        type: new Set(),\n        class: new Set(),\n        id: new Set(),\n        universal: new Set(),\n        attribute: new Set(),\n\n        // Non-simple.\n        nonSimple: new Set()\n      };\n\n      for (const styleSheet of document.styleSheets) {\n        if (styleSheet.href) {\n          externalSheets++;\n        } else {\n          inlineStyles++;\n        }\n\n        // Attempting to grab rules can trigger a DOMException.\n        // Try it and if it fails skip to the next stylesheet.\n        let rules;\n        try {\n          rules = styleSheet.rules;\n        } catch (err) {\n          continue;\n        }\n\n        for (const rule of rules) {\n          if ('selectorText' in rule) {\n            styleRules++;\n\n            // Each group that was used.\n            for (const selectorGroup of rule.selectorText.split(',')) {\n              // Each selector in the group.\n              for (const selector of selectorGroup.split(/[\\t\\n\\f\\r ]+/g)) {\n                if (selector.startsWith('.')) {\n                  // Class.\n                  stats.class.add(selector);\n                } else if (selector.startsWith('#')) {\n                  // Id.\n                  stats.id.add(selector);\n                } else if (selector.startsWith('*')) {\n                  // Universal.\n                  stats.universal.add(selector);\n                } else if (selector.startsWith('[')) {\n                  // Attribute.\n                  stats.attribute.add(selector);\n                } else {\n                  // Type or non-simple selector.\n                  const specialChars = /[#.:\\[\\]|\\+>~]/;\n                  if (specialChars.test(selector)) {\n                    stats.nonSimple.add(selector);\n                  } else {\n                    stats.type.add(selector);\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n\n      return {\n        styleRules,\n        inlineStyles,\n        externalSheets,\n        stats: {\n          // Simple.\n          type: stats.type.size,\n          class: stats.class.size,\n          id: stats.id.size,\n          universal: stats.universal.size,\n          attribute: stats.attribute.size,\n\n          // Non-simple.\n          nonSimple: stats.nonSimple.size\n        }\n      }\n    })()",returnByValue:!0});if("object"===e.type)return e.value}}t.SDKModel.SDKModel.register(S,{capabilities:t.Target.Capability.DOM,autostart:!1});var C=Object.freeze({__proto__:null,CSSOverviewModel:S});const y=new CSSStyleSheet;y.replaceSync(".overview-processing-view{overflow:hidden;padding:16px;justify-content:center;align-items:center;height:100%}.overview-processing-view h1{font-size:16px;text-align:center;font-weight:normal;margin:0;padding:8px}.overview-processing-view h2{font-size:12px;text-align:center;font-weight:normal;margin:0;padding-top:32px}\n/*# sourceURL=cssOverviewProcessingView.css */\n");const x={cancel:"Cancel"},k=i.i18n.registerUIStrings("panels/css_overview/CSSOverviewProcessingView.ts",x),I=i.i18n.getLocalizedString.bind(void 0,k);class T extends s.Widget.Widget{#s;fragment;constructor(e){super(),this.#s=e,this.#r()}#r(){const e=s.UIUtils.createTextButton(I(x.cancel),(()=>this.#s.dispatchEventToListeners("RequestOverviewCancel")),"",!0);this.setDefaultFocusedElement(e),this.fragment=s.Fragment.Fragment.build`
      <div class="vbox overview-processing-view">
        <h1>Processing page</h1>
        <div>${e}</div>
      </div>
    `,this.contentElement.appendChild(this.fragment.element()),this.contentElement.style.overflow="auto"}wasShown(){super.wasShown(),this.registerCSSFiles([y])}}var M=Object.freeze({__proto__:null,CSSOverviewProcessingView:T});const $=new CSSStyleSheet;$.replaceSync('.overview-completed-view{overflow:auto;--overview-default-padding:28px;--overview-icon-padding:32px}.overview-completed-view .summary ul,\n.overview-completed-view .colors ul{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.overview-completed-view .summary ul{display:grid;grid-template-columns:repeat(auto-fill,140px);grid-gap:16px}.overview-completed-view .colors ul li{display:inline-block;margin:0 0 16px;padding:0 8px 0 0}.overview-completed-view .summary ul li{display:flex;flex-direction:column;grid-column-start:auto}.overview-completed-view li .label{font-size:12px;padding-bottom:2px}.overview-completed-view li .value{font-size:17px}.overview-completed-view ul li span{font-weight:bold}.unused-rules-grid .header-container,\n.unused-rules-grid .data-container,\n.unused-rules-grid table.data{position:relative}.unused-rules-grid .data-container{top:0;max-height:350px}.unused-rules-grid{border-left:none;border-right:none}.unused-rules-grid .monospace{display:block;height:18px}.element-grid{flex:1;border-left:none;border-right:none;overflow:auto}.block{width:65px;height:25px;border-radius:3px;margin-right:16px}.block-title{padding-top:4px;font-size:12px;color:var(--color-text-primary);letter-spacing:0;text-transform:uppercase}.block-title.color-text{text-transform:none;max-width:65px;text-overflow:ellipsis;white-space:nowrap;cursor:text;user-select:text;overflow:hidden}.results-section{flex-shrink:0;border-bottom:1px solid var(--color-details-hairline);padding:var(--overview-default-padding) 0 var(--overview-default-padding) 0}.horizontally-padded{padding-left:var(--overview-default-padding);padding-right:var(--overview-default-padding)}.results-section h1{font-size:15px;font-weight:normal;padding:0;margin:0 0 20px;padding-left:calc(var(--overview-default-padding) + var(--overview-icon-padding));position:relative;height:26px;line-height:26px}.results-section h1::before{content:"";display:block;position:absolute;left:var(--overview-default-padding);top:0;width:26px;height:26px;background-image:var(--image-file-cssoverview_icons_2x);background-size:104px 26px}.results-section.horizontally-padded h1{padding-left:var(--overview-icon-padding)}.results-section.horizontally-padded h1::before{left:0}.results-section.summary h1{padding-left:0}.results-section.summary h1::before{display:none}.results-section.colors h1::before{background-position:0 0}.results-section.font-info h1::before{background-position:-26px 0}.results-section.unused-declarations h1::before{background-position:-52px 0}.results-section.media-queries h1::before{background-position:-78px 0}.results-section.colors h2{margin-top:20px;font-size:13px;font-weight:normal}.overview-completed-view .font-info ul,\n.overview-completed-view .media-queries ul,\n.overview-completed-view .unused-declarations ul{width:100%;list-style:none;margin:0;padding:0 var(--overview-default-padding)}.overview-completed-view .font-info ul li,\n.overview-completed-view .media-queries ul li,\n.overview-completed-view .unused-declarations ul li{display:grid;grid-template-columns:2fr 3fr;grid-gap:12px;margin-bottom:4px;align-items:center}.overview-completed-view .font-info button,\n.overview-completed-view .media-queries button,\n.overview-completed-view .unused-declarations button{border:none;padding:0;margin:0;display:flex;align-items:center;border-radius:2px;cursor:pointer;height:28px;background:none}.overview-completed-view .font-info button .details,\n.overview-completed-view .media-queries button .details,\n.overview-completed-view .unused-declarations button .details{min-width:100px;text-align:right;margin-right:8px;color:var(--color-primary-old);pointer-events:none}.overview-completed-view .font-info button .bar-container,\n.overview-completed-view .media-queries button .bar-container,\n.overview-completed-view .unused-declarations button .bar-container{flex:1;pointer-events:none}.overview-completed-view .font-info button .bar,\n.overview-completed-view .media-queries button .bar,\n.overview-completed-view .unused-declarations button .bar{height:8px;background:var(--color-primary-old);border-radius:2px;min-width:2px}.overview-completed-view .font-info button:hover .details,\n.overview-completed-view .font-info button:focus .details,\n.overview-completed-view .media-queries button:hover .details,\n.overview-completed-view .media-queries button:focus .details,\n.overview-completed-view .unused-declarations button:hover .details,\n.overview-completed-view .unused-declarations button:focus .details{color:var(--color-primary-variant)}.overview-completed-view .font-info button:hover .bar,\n.overview-completed-view .font-info button:focus .bar,\n.overview-completed-view .media-queries button:hover .bar,\n.overview-completed-view .media-queries button:focus .bar,\n.overview-completed-view .unused-declarations button:hover .bar,\n.overview-completed-view .unused-declarations button:focus .bar{background-color:var(--color-primary-variant);box-shadow:0 1px 2px var(--divider-line),0 0 0 2px var(--color-primary-variant);color:var(--color-background)}.overview-completed-view .font-info .font-metric{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));grid-gap:12px}.overview-completed-view .font-info ul{padding:0}.overview-completed-view .font-info ul li{grid-template-columns:1fr 4fr}.overview-completed-view .font-info h2{font-size:14px;font-weight:bold;margin:0 0 1em}.overview-completed-view .font-info h3{font-size:13px;font-weight:normal;font-style:italic;margin:0 0 0.5em}.overview-completed-view .font-info{padding-bottom:0}.overview-completed-view .font-family{padding:var(--overview-default-padding)}.overview-completed-view .font-family:nth-child(2n+1){background:var(--color-background)}.overview-completed-view .font-family:first-of-type{padding-top:0}.contrast-warning{display:flex;align-items:center;margin-top:2px}.contrast-warning .threshold-label{font-weight:normal;width:30px}.contrast-warning devtools-icon{margin-left:2px}.contrast-preview{padding:0 5px}.contrast-container-in-grid{display:flex;align-items:center}.contrast-container-in-grid > *{margin-right:5px;min-width:initial}.data .nodeId-column{align-items:center;display:flex;height:20px}.nodeId-column .monospace{overflow:hidden}.show-element{margin:0 0 0 8px;display:none;cursor:pointer;flex:none;--icon-show-element:var(--icon-default)}.show-element:focus,\n.show-element:hover{--icon-show-element:var(--icon-default-hover)}.nodeId-column:focus-within .show-element,\n.nodeId-column:hover .show-element{display:inline-block}.results-section.colors{forced-color-adjust:none}\n/*# sourceURL=cssOverviewCompletedView.css */\n');const A=new CSSStyleSheet;A.replaceSync(".overview-sidebar-panel{overflow:auto;display:flex;background:var(--color-background-elevation-1)}.overview-sidebar-panel-item{height:30px;padding-left:30px;display:flex;align-items:center;color:var(--color-text-primary);white-space:nowrap}.overview-sidebar-panel-container{min-width:fit-content}.overview-sidebar-panel-item:hover,\n.overview-sidebar-panel-item:focus{background:var(--color-background-highlight)}.overview-sidebar-panel-item.selected{background:var(--color-primary-old);color:var(--color-background)}.overview-toolbar{border-bottom:1px solid var(--color-details-hairline);flex:0 0 auto}.overview-sidebar-panel-item:focus-visible{outline-width:unset}@media (forced-colors: active){.overview-sidebar-panel-item.selected{forced-color-adjust:none;background:Highlight;color:HighlightText}.overview-sidebar-panel-item:hover{forced-color-adjust:none;background:Highlight;color:HighlightText}}\n/*# sourceURL=cssOverviewSidebarPanel.css */\n");const E={clearOverview:"Clear overview",cssOverviewPanelSidebar:"CSS Overview panel sidebar"},L=i.i18n.registerUIStrings("panels/css_overview/CSSOverviewSidebarPanel.ts",E),F=i.i18n.getLocalizedString.bind(void 0,L);class O extends(e.ObjectWrapper.eventMixin(s.Widget.VBox)){containerElement;static get ITEM_CLASS_NAME(){return"overview-sidebar-panel-item"}static get SELECTED(){return"selected"}constructor(){super(!0),this.contentElement.classList.add("overview-sidebar-panel"),this.contentElement.addEventListener("click",this.#a.bind(this)),this.contentElement.addEventListener("keydown",this.#l.bind(this)),this.containerElement=this.contentElement.createChild("div","overview-sidebar-panel-container"),s.ARIAUtils.setLabel(this.containerElement,F(E.cssOverviewPanelSidebar)),s.ARIAUtils.markAsTree(this.containerElement);const e=new s.Toolbar.ToolbarButton(F(E.clearOverview),"clear");e.addEventListener(s.Toolbar.ToolbarButton.Events.Click,this.#d,this);const t=this.containerElement.createChild("div","overview-toolbar");new s.Toolbar.Toolbar("",t).appendToolbarItem(e)}addItem(e,t){const i=this.containerElement.createChild("div",O.ITEM_CLASS_NAME);s.ARIAUtils.markAsTreeitem(i),i.textContent=e,i.dataset.id=t,i.tabIndex=0}#d(){this.dispatchEventToListeners("Reset")}#c(){this.containerElement.querySelectorAll(`.${O.ITEM_CLASS_NAME}`).forEach((e=>{e.classList.remove(O.SELECTED)}))}#a(e){const t=e.composedPath()[0];if(!t.classList.contains(O.ITEM_CLASS_NAME))return;const{id:i}=t.dataset;i&&(this.select(i),this.dispatchEventToListeners("ItemSelected",{id:i,isMouseEvent:!0}))}#l(e){if("Enter"!==e.key)return;const t=e.composedPath()[0];if(!t.classList.contains(O.ITEM_CLASS_NAME))return;const{id:i}=t.dataset;i&&(this.select(i),this.dispatchEventToListeners("ItemSelected",{id:i,isMouseEvent:!1}),e.consume(!0))}select(e){const t=this.containerElement.querySelector(`[data-id=${CSS.escape(e)}]`);t&&(t.classList.contains(O.SELECTED)||(this.#c(),t.classList.add(O.SELECTED)))}wasShown(){super.wasShown(),this.registerCSSFiles([A])}}var R=Object.freeze({__proto__:null,CSSOverviewSidebarPanel:O});const P={overviewSummary:"Overview summary",colors:"Colors",fontInfo:"Font info",unusedDeclarations:"Unused declarations",mediaQueries:"Media queries",elements:"Elements",externalStylesheets:"External stylesheets",inlineStyleElements:"Inline style elements",styleRules:"Style rules",typeSelectors:"Type selectors",idSelectors:"ID selectors",classSelectors:"Class selectors",universalSelectors:"Universal selectors",attributeSelectors:"Attribute selectors",nonsimpleSelectors:"Non-simple selectors",backgroundColorsS:"Background colors: {PH1}",textColorsS:"Text colors: {PH1}",fillColorsS:"Fill colors: {PH1}",borderColorsS:"Border colors: {PH1}",thereAreNoFonts:"There are no fonts.",thereAreNoUnusedDeclarations:"There are no unused declarations.",thereAreNoMediaQueries:"There are no media queries.",contrastIssues:"Contrast issues",nOccurrences:"{n, plural, =1 {# occurrence} other {# occurrences}}",contrastIssuesS:"Contrast issues: {PH1}",textColorSOverSBackgroundResults:"Text color {PH1} over {PH2} background results in low contrast for {PH3} elements",aa:"AA",aaa:"AAA",apca:"APCA",element:"Element",declaration:"Declaration",source:"Source",contrastRatio:"Contrast ratio",cssOverviewElements:"CSS Overview Elements",showElement:"Show element"},_=i.i18n.registerUIStrings("panels/css_overview/CSSOverviewCompletedView.ts",P),V=i.i18n.getLocalizedString.bind(void 0,_);function N(e){let{h:t,s:i,l:o}=e.as("hsl");return t=Math.round(360*t),i=Math.round(100*i),o=Math.round(100*o),o=Math.max(0,o-15),`1px solid hsl(${t}deg ${i}% ${o}%)`}class D extends s.Panel.PanelWithSidebar{#s;#h;#u;#v;#p;#m;#g;#w;#f;#b;#S;#C;constructor(e){super("css_overview_completed_view"),this.#s=e,this.#h=new Intl.NumberFormat("en-US"),this.#u=new s.SplitWidget.SplitWidget(!0,!0),this.#v=new s.Widget.VBox,this.#p=new z,this.#p.addEventListener("TabClosed",(e=>{0===e.data&&this.#u.setSidebarMinimized(!0)})),this.#u.setMainWidget(this.#v),this.#u.setSidebarWidget(this.#p),this.#u.setVertical(!1),this.#u.setSecondIsSidebar(!0),this.#u.setSidebarMinimized(!0),this.#m=new O,this.#m.setMinimumSize(100,25),this.splitWidget().setSidebarWidget(this.#m),this.splitWidget().setMainWidget(this.#u),this.#f=new c.Linkifier.Linkifier(20,!0),this.#b=new Map,this.#m.addItem(V(P.overviewSummary),"summary"),this.#m.addItem(V(P.colors),"colors"),this.#m.addItem(V(P.fontInfo),"font-info"),this.#m.addItem(V(P.unusedDeclarations),"unused-declarations"),this.#m.addItem(V(P.mediaQueries),"media-queries"),this.#m.select("summary"),this.#m.addEventListener("ItemSelected",this.#y,this),this.#m.addEventListener("Reset",this.#x,this),this.#s.addEventListener("Reset",this.#d,this),this.#s.addEventListener("PopulateNodes",this.#k,this),this.#v.element.addEventListener("click",this.#I.bind(this)),this.#S=null}wasShown(){super.wasShown(),this.#u.registerCSSFiles([$]),this.registerCSSFiles([$])}initializeModels(e){const i=e.model(t.CSSModel.CSSModel),o=e.model(t.DOMModel.DOMModel);if(!i||!o)throw new Error("Target must provide CSS and DOM models");this.#g=i,this.#w=o}#y(e){const{data:t}=e,i=this.#C.$(t.id);if(i&&(i.scrollIntoView(),!t.isMouseEvent)){i.querySelector('button, [tabindex="0"]')?.focus()}}#x(){this.#s.dispatchEventToListeners("Reset")}#d(){this.#v.element.removeChildren(),this.#u.setSidebarMinimized(!0),this.#p.closeTabs(),this.#b=new Map,D.pushedNodes.clear(),this.#m.select("summary")}#I(e){if(!e.target)return;const t=e.target.dataset,i=t.type;if(!i||!this.#S)return;let o;switch(i){case"contrast":{const e=t.section,n=t.key;if(!n)return;o={type:i,key:n,nodes:this.#S.textColorContrastIssues.get(n)||[],section:e};break}case"color":{const e=t.color,n=t.section;if(!e)return;let s;switch(n){case"text":s=this.#S.textColors.get(e);break;case"background":s=this.#S.backgroundColors.get(e);break;case"fill":s=this.#S.fillColors.get(e);break;case"border":s=this.#S.borderColors.get(e)}if(!s)return;s=Array.from(s).map((e=>({nodeId:e}))),o={type:i,color:e,nodes:s,section:n};break}case"unused-declarations":{const e=t.declaration;if(!e)return;const n=this.#S.unusedDeclarations.get(e);if(!n)return;o={type:i,declaration:e,nodes:n};break}case"media-queries":{const e=t.text;if(!e)return;const n=this.#S.mediaQueries.get(e);if(!n)return;o={type:i,text:e,nodes:n};break}case"font-info":{const e=t.value;if(!t.path)return;const[n,s]=t.path.split("/");if(!e)return;const r=this.#S.fontInfo.get(n);if(!r)return;const a=r.get(s);if(!a)return;const l=a.get(e);if(!l)return;o={type:i,name:`${e} (${n}, ${s})`,nodes:l.map((e=>({nodeId:e})))};break}default:return}e.consume(),this.#s.dispatchEventToListeners("PopulateNodes",{payload:o}),this.#u.setSidebarMinimized(!1)}async#r(e){if(!e||!("backgroundColors"in e)||!("textColors"in e))return;this.#S=e;const{elementCount:t,backgroundColors:i,textColors:o,textColorContrastIssues:n,fillColors:r,borderColors:a,globalStyleStats:l,mediaQueries:d,unusedDeclarations:c,fontInfo:h}=this.#S,u=this.#T(i),v=this.#T(o),p=this.#T(r),m=this.#T(a);this.#C=s.Fragment.Fragment.build`
    <div class="vbox overview-completed-view">
      <div $="summary" class="results-section horizontally-padded summary">
        <h1>${V(P.overviewSummary)}</h1>

        <ul>
          <li>
            <div class="label">${V(P.elements)}</div>
            <div class="value">${this.#h.format(t)}</div>
          </li>
          <li>
            <div class="label">${V(P.externalStylesheets)}</div>
            <div class="value">${this.#h.format(l.externalSheets)}</div>
          </li>
          <li>
            <div class="label">${V(P.inlineStyleElements)}</div>
            <div class="value">${this.#h.format(l.inlineStyles)}</div>
          </li>
          <li>
            <div class="label">${V(P.styleRules)}</div>
            <div class="value">${this.#h.format(l.styleRules)}</div>
          </li>
          <li>
            <div class="label">${V(P.mediaQueries)}</div>
            <div class="value">${this.#h.format(d.size)}</div>
          </li>
          <li>
            <div class="label">${V(P.typeSelectors)}</div>
            <div class="value">${this.#h.format(l.stats.type)}</div>
          </li>
          <li>
            <div class="label">${V(P.idSelectors)}</div>
            <div class="value">${this.#h.format(l.stats.id)}</div>
          </li>
          <li>
            <div class="label">${V(P.classSelectors)}</div>
            <div class="value">${this.#h.format(l.stats.class)}</div>
          </li>
          <li>
            <div class="label">${V(P.universalSelectors)}</div>
            <div class="value">${this.#h.format(l.stats.universal)}</div>
          </li>
          <li>
            <div class="label">${V(P.attributeSelectors)}</div>
            <div class="value">${this.#h.format(l.stats.attribute)}</div>
          </li>
          <li>
            <div class="label">${V(P.nonsimpleSelectors)}</div>
            <div class="value">${this.#h.format(l.stats.nonSimple)}</div>
          </li>
        </ul>
      </div>

      <div $="colors" class="results-section horizontally-padded colors">
        <h1>${V(P.colors)}</h1>
        <h2>${V(P.backgroundColorsS,{PH1:u.length})}</h2>
        <ul>
          ${u.map(this.#M.bind(this,"background"))}
        </ul>

        <h2>${V(P.textColorsS,{PH1:v.length})}</h2>
        <ul>
          ${v.map(this.#M.bind(this,"text"))}
        </ul>

        ${n.size>0?this.#$(n):""}

        <h2>${V(P.fillColorsS,{PH1:p.length})}</h2>
        <ul>
          ${p.map(this.#M.bind(this,"fill"))}
        </ul>

        <h2>${V(P.borderColorsS,{PH1:m.length})}</h2>
        <ul>
          ${m.map(this.#M.bind(this,"border"))}
        </ul>
      </div>

      <div $="font-info" class="results-section font-info">
        <h1>${V(P.fontInfo)}</h1>
        ${h.size>0?this.#A(h):s.Fragment.Fragment.build`<div>${V(P.thereAreNoFonts)}</div>`}
      </div>

      <div $="unused-declarations" class="results-section unused-declarations">
        <h1>${V(P.unusedDeclarations)}</h1>
        ${c.size>0?this.#E(c,"unused-declarations","declaration"):s.Fragment.Fragment.build`<div class="horizontally-padded">${V(P.thereAreNoUnusedDeclarations)}</div>`}
      </div>

      <div $="media-queries" class="results-section media-queries">
        <h1>${V(P.mediaQueries)}</h1>
        ${d.size>0?this.#E(d,"media-queries","text"):s.Fragment.Fragment.build`<div class="horizontally-padded">${V(P.thereAreNoMediaQueries)}</div>`}
      </div>
    </div>`,this.#v.element.appendChild(this.#C.element())}#k(e){const{payload:t}=e.data;let i="",o="";switch(t.type){case"contrast":{const{section:e,key:n}=t;i=`${e}-${n}`,o=V(P.contrastIssues);break}case"color":{const{section:e,color:n}=t;i=`${e}-${n}`,o=`${n.toUpperCase()} (${e})`;break}case"unused-declarations":{const{declaration:e}=t;i=`${e}`,o=`${e}`;break}case"media-queries":{const{text:e}=t;i=`${e}`,o=`${e}`;break}case"font-info":{const{name:e}=t;i=`${e}`,o=`${e}`;break}}let n=this.#b.get(i);if(!n){if(!this.#w||!this.#g)throw new Error("Unable to initialize CSS Overview, missing models");n=new W(this.#s,this.#w,this.#g,this.#f),n.populateNodes(t.nodes),this.#b.set(i,n)}this.#p.appendTab(i,o,n,!0)}#A(e){const t=Array.from(e.entries());return s.Fragment.Fragment.build`
  ${t.map((([e,t])=>s.Fragment.Fragment.build`<section class="font-family"><h2>${e}</h2> ${this.#L(e,t)}</section>`))}
  `}#L(e,t){const i=Array.from(t.entries());return s.Fragment.Fragment.build`
  <div class="font-metric">
  ${i.map((([t,i])=>{const o=`${e}/${t}`;return s.Fragment.Fragment.build`
  <div>
  <h3>${t}</h3>
  ${this.#E(i,"font-info","value",o)}
  </div>`}))}
  </div>`}#E(e,t,i,o=""){const n=Array.from(e.entries()).sort(((e,t)=>{const i=e[1];return t[1].length-i.length})),r=n.reduce(((e,t)=>e+t[1].length),0);return s.Fragment.Fragment.build`<ul>
    ${n.map((([e,n])=>{const a=100*n.length/r,l=V(P.nOccurrences,{n:n.length});return s.Fragment.Fragment.build`<li>
        <div class="title">${e}</div>
        <button data-type="${t}" data-path="${o}" data-${i}="${e}">
          <div class="details">${l}</div>
          <div class="bar-container">
            <div class="bar" style="width: ${a}%;"></div>
          </div>
        </button>
      </li>`}))}
    </ul>`}#$(e){return s.Fragment.Fragment.build`
  <h2>${V(P.contrastIssuesS,{PH1:e.size})}</h2>
  <ul>
  ${[...e.entries()].map((([e,t])=>this.#F(e,t)))}
  </ul>
  `}#F(e,t){console.assert(t.length>0);let i=t[0];for(const e of t)Math.abs(e.contrastRatio)<Math.abs(i.contrastRatio)&&(i=e);const n=i.textColor.asString("hexa"),r=i.backgroundColor.asString("hexa"),a=o.Runtime.experiments.isEnabled("APCA"),l=V(P.textColorSOverSBackgroundResults,{PH1:n,PH2:r,PH3:t.length}),d=s.Fragment.Fragment.build`<li>
      <button
        title="${l}" aria-label="${l}"
        data-type="contrast" data-key="${e}" data-section="contrast" class="block" $="color">
        Text
      </button>
      <div class="block-title">
        <div class="contrast-warning hidden" $="aa"><span class="threshold-label">${V(P.aa)}</span></div>
        <div class="contrast-warning hidden" $="aaa"><span class="threshold-label">${V(P.aaa)}</span></div>
        <div class="contrast-warning hidden" $="apca"><span class="threshold-label">${V(P.apca)}</span></div>
      </div>
    </li>`;if(a){const e=d.$("apca");i.thresholdsViolated.apca?e.appendChild(B()):e.appendChild(H()),e.classList.remove("hidden")}else{const e=d.$("aa");i.thresholdsViolated.aa?e.appendChild(B()):e.appendChild(H());const t=d.$("aaa");i.thresholdsViolated.aaa?t.appendChild(B()):t.appendChild(H()),e.classList.remove("hidden"),t.classList.remove("hidden")}const c=d.$("color");return c.style.backgroundColor=r,c.style.color=n,c.style.border=N(i.backgroundColor.asLegacyColor()),d}#M(t,i){const o=s.Fragment.Fragment.build`<li>
      <button title=${i} data-type="color" data-color="${i}"
        data-section="${t}" class="block" $="color"></button>
      <div class="block-title color-text">${i}</div>
    </li>`,n=o.$("color");n.style.backgroundColor=i;const r=e.Color.parse(i)?.asLegacyColor();if(r)return n.style.border=N(r),o}#T(t){return Array.from(t.keys()).sort(((t,i)=>{const o=e.Color.parse(t)?.asLegacyColor(),n=e.Color.parse(i)?.asLegacyColor();return o&&n?e.ColorUtils.luminance(n.rgba())-e.ColorUtils.luminance(o.rgba()):0}))}setOverviewData(e){this.#r(e)}static pushedNodes=new Set}class z extends(e.ObjectWrapper.eventMixin(s.Widget.VBox)){#O;constructor(){super(),this.#O=new s.TabbedPane.TabbedPane,this.#O.show(this.element),this.#O.addEventListener(s.TabbedPane.Events.TabClosed,(()=>{this.dispatchEventToListeners("TabClosed",this.#O.tabIds().length)}))}appendTab(e,t,i,o){this.#O.hasTab(e)||this.#O.appendTab(e,t,i,void 0,void 0,o),this.#O.selectTab(e)}closeTabs(){this.#O.closeTabs(this.#O.tabIds())}}class W extends s.Widget.Widget{#s;#w;#g;#f;#R;#P;constructor(e,t,i,o){super(),this.#s=e,this.#w=t,this.#g=i,this.#f=o,this.#R=[{id:"nodeId",title:V(P.element),sortable:!0,weight:50,titleDOMFragment:void 0,sort:void 0,align:void 0,width:void 0,fixedWidth:void 0,editable:void 0,nonSelectable:void 0,longText:void 0,disclosure:void 0,allowInSortByEvenWhenHidden:void 0,dataType:void 0,defaultWeight:void 0},{id:"declaration",title:V(P.declaration),sortable:!0,weight:50,titleDOMFragment:void 0,sort:void 0,align:void 0,width:void 0,fixedWidth:void 0,editable:void 0,nonSelectable:void 0,longText:void 0,disclosure:void 0,allowInSortByEvenWhenHidden:void 0,dataType:void 0,defaultWeight:void 0},{id:"sourceURL",title:V(P.source),sortable:!1,weight:100,titleDOMFragment:void 0,sort:void 0,align:void 0,width:void 0,fixedWidth:void 0,editable:void 0,nonSelectable:void 0,longText:void 0,disclosure:void 0,allowInSortByEvenWhenHidden:void 0,dataType:void 0,defaultWeight:void 0},{id:"contrastRatio",title:V(P.contrastRatio),sortable:!0,weight:25,titleDOMFragment:void 0,sort:void 0,align:void 0,width:"150px",fixedWidth:!0,editable:void 0,nonSelectable:void 0,longText:void 0,disclosure:void 0,allowInSortByEvenWhenHidden:void 0,dataType:void 0,defaultWeight:void 0}],this.#P=new d.SortableDataGrid.SortableDataGrid({displayName:V(P.cssOverviewElements),columns:this.#R,editCallback:void 0,deleteCallback:void 0,refreshCallback:void 0}),this.#P.element.classList.add("element-grid"),this.#P.element.addEventListener("mouseover",this.#_.bind(this)),this.#P.setStriped(!0),this.#P.addEventListener(d.DataGrid.Events.SortingChanged,this.#V.bind(this)),this.#P.asWidget().show(this.element)}#V(){const e=this.#P.sortColumnId();if(!e)return;const t=d.SortableDataGrid.SortableDataGrid.StringComparator.bind(null,e);this.#P.sortNodes(t,!this.#P.isSortOrderAscending())}#_(e){const t=e.composedPath().find((e=>e.dataset&&e.dataset.backendNodeId));if(!t)return;const i=Number(t.dataset.backendNodeId);this.#s.dispatchEventToListeners("RequestNodeHighlight",i)}async populateNodes(e){if(this.#P.rootNode().removeChildren(),!e.length)return;const[t]=e,i=new Set;let o;if("nodeId"in t&&t.nodeId&&i.add("nodeId"),"declaration"in t&&t.declaration&&i.add("declaration"),"sourceURL"in t&&t.sourceURL&&i.add("sourceURL"),"contrastRatio"in t&&t.contrastRatio&&i.add("contrastRatio"),"nodeId"in t&&i.has("nodeId")){const t=e.reduce(((e,t)=>{const i=t.nodeId;return D.pushedNodes.has(i)?e:(D.pushedNodes.add(i),e.add(i))}),new Set);o=await this.#w.pushNodesByBackendIdsToFrontend(t)}for(const t of e){let e;if("nodeId"in t&&i.has("nodeId")){if(!o)continue;if(e=o.get(t.nodeId),!e)continue}const n=new U(t,e,this.#f,this.#g);n.selectable=!1,this.#P.insertChild(n)}this.#P.setColumnsVisiblity(i),this.#P.renderInline(),this.#P.wasShown()}}class U extends d.SortableDataGrid.SortableDataGridNode{#f;#g;#N;constructor(e,t,i,o){super(e),this.#N=t,this.#f=i,this.#g=o}createCell(t){const i=this.#N;if("nodeId"===t){const o=this.createTD(t);if(o.textContent="...",!i)throw new Error("Node entry is missing a related frontend node.");return e.Linkifier.Linkifier.linkify(i).then((e=>{o.textContent="",e.dataset.backendNodeId=i.backendNodeId().toString(),o.appendChild(e);const t=new l.Icon.Icon;t.data={iconName:"select-element",color:"var(--icon-show-element)",width:"16px"},t.classList.add("show-element"),s.Tooltip.Tooltip.install(t,V(P.showElement)),t.tabIndex=0,t.onclick=()=>i.scrollIntoView(),o.appendChild(t)})),o}if("sourceURL"===t){const e=this.createTD(t);if(this.data.range){const t=this.#D(this.#g,this.#f,this.data.styleSheetId,a.TextRange.TextRange.fromObject(this.data.range));t&&""!==t.textContent?e.appendChild(t):e.textContent="(unable to link)"}else e.textContent="(unable to link to inlined styles)";return e}if("contrastRatio"===t){const e=this.createTD(t),i=o.Runtime.experiments.isEnabled("APCA"),n=r.NumberUtilities.floor(this.data.contrastRatio,2),a=i?n+"%":n,l=N(this.data.backgroundColor),d=this.data.textColor.asString(),c=this.data.backgroundColor.asString(),h=s.Fragment.Fragment.build`
        <div class="contrast-container-in-grid" $="container">
          <span class="contrast-preview" style="border: ${l};
          color: ${d};
          background-color: ${c};">Aa</span>
          <span>${a}</span>
        </div>
      `,u=h.$("container");return i?(u.append(s.Fragment.Fragment.build`<span>${V(P.apca)}</span>`.element()),this.data.thresholdsViolated.apca?u.appendChild(B()):u.appendChild(H())):(u.append(s.Fragment.Fragment.build`<span>${V(P.aa)}</span>`.element()),this.data.thresholdsViolated.aa?u.appendChild(B()):u.appendChild(H()),u.append(s.Fragment.Fragment.build`<span>${V(P.aaa)}</span>`.element()),this.data.thresholdsViolated.aaa?u.appendChild(B()):u.appendChild(H())),e.appendChild(h.element()),e}return super.createCell(t)}#D(e,i,o,n){const s=e.styleSheetHeaderForId(o);if(!s)return;const r=s.lineNumberInSource(n.startLine),a=s.columnNumberInSource(n.startLine,n.startColumn),l=new t.CSSModel.CSSLocation(s,r,a);return i.linkifyCSSLocation(l)}}function B(){const e=new l.Icon.Icon;return e.data={iconName:"clear",color:"var(--icon-error)",width:"14px",height:"14px"},e}function H(){const e=new l.Icon.Icon;return e.data={iconName:"checkmark",color:"var(--icon-checkmark-green)",width:"14px",height:"14px"},e}var G=Object.freeze({__proto__:null,CSSOverviewCompletedView:D,DetailsView:z,ElementDetailsView:W,ElementNode:U});const j=new CSSStyleSheet;j.replaceSync(".css-overview-panel{overflow:hidden}devtools-css-overview-start-view{overflow:auto}\n/*# sourceURL=cssOverview.css */\n");class q extends s.Panel.Panel{#s;#z;#W;#U;#B;#H;#G;#j;#q;#Q;#K;#J;#X;#Y;#Z;constructor(e){super("css_overview"),this.element.classList.add("css-overview-panel"),this.#s=e,this.#z=new h.CSSOverviewStartView.CSSOverviewStartView,this.#z.addEventListener("overviewstartrequested",(()=>this.#s.dispatchEventToListeners("RequestOverviewStart"))),this.#W=new T(this.#s),this.#U=new D(this.#s),t.TargetManager.TargetManager.instance().observeTargets(this),this.#s.addEventListener("RequestOverviewStart",(e=>{u.userMetrics.actionTaken(u.UserMetrics.Action.CaptureCssOverviewClicked),this.#ee()}),this),this.#s.addEventListener("OverviewCompleted",this.#te,this),this.#s.addEventListener("Reset",this.#d,this),this.#s.addEventListener("RequestNodeHighlight",this.#ie,this),this.#d()}targetAdded(e){if(e!==t.TargetManager.TargetManager.instance().primaryPageTarget())return;this.#U.initializeModels(e);const i=e.model(S);this.#B=i}targetRemoved(){}#oe(){if(!this.#B)throw new Error("Did not retrieve model information yet.");return this.#B}#d(){this.#H=new Map,this.#G=new Map,this.#j=new Map,this.#q=new Map,this.#Q=new Map,this.#K=new Map,this.#J=new Map,this.#X=0,this.#Y={styleRules:0,inlineStyles:0,externalSheets:0,stats:{type:0,class:0,id:0,universal:0,attribute:0,nonSimple:0}},this.#Z=new Map,this.#ne()}#ie(e){this.#oe().highlightNode(e.data)}#ne(){this.#W.hideWidget(),this.#U.hideWidget(),this.contentElement.append(this.#z),this.#z.show()}#se(){this.#z.hide(),this.#U.hideWidget(),this.#W.show(this.contentElement)}#re(){this.#z.hide(),this.#W.hideWidget(),this.#U.show(this.contentElement),this.#U.setOverviewData({backgroundColors:this.#H,textColors:this.#G,textColorContrastIssues:this.#Z,fillColors:this.#j,borderColors:this.#q,globalStyleStats:this.#Y,fontInfo:this.#Q,elementCount:this.#X,mediaQueries:this.#K,unusedDeclarations:this.#J})}async#ee(){this.#se();const e=this.#oe(),[t,{elementCount:i,backgroundColors:o,textColors:n,textColorContrastIssues:s,fillColors:r,borderColors:a,fontInfo:l,unusedDeclarations:d},c]=await Promise.all([e.getGlobalStylesheetStats(),e.getNodeStyleStats(),e.getMediaQueries()]);i&&(this.#X=i),t&&(this.#Y=t),c&&(this.#K=c),o&&(this.#H=o),n&&(this.#G=n),s&&(this.#Z=s),r&&(this.#j=r),a&&(this.#q=a),l&&(this.#Q=l),d&&(this.#J=d),this.#s.dispatchEventToListeners("OverviewCompleted")}#te(){this.#re()}wasShown(){super.wasShown(),this.registerCSSFiles([j])}}var Q=Object.freeze({__proto__:null,CSSOverviewPanel:q});export{G as CSSOverviewCompletedView,p as CSSOverviewController,C as CSSOverviewModel,Q as CSSOverviewPanel,M as CSSOverviewProcessingView,R as CSSOverviewSidebarPanel,b as CSSOverviewUnusedDeclarations};
